package org.virbraligo.vboxjavaservice;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HeadlessProcessMonitor extends Thread {
	static Logger logger = Logger.getLogger(HeadlessProcessMonitor.class
			.getName());
	String headlesspid;

	public static boolean headlessAlive = false;

	private int headlessPidCheckInterval = Integer.parseInt(System.getProperty(
			"headlessPidCheckInterval", "5000"));

	private List processes = new ArrayList();

	public static byte[] headlesspidCheckLock = new byte[0];

	public HeadlessProcessMonitor(String headlesspid) {
		this.headlesspid = headlesspid;
	}

	public void run() {
		while (VBoxJavaService.active) {
			processes.clear();
			try {
				Process p = Runtime.getRuntime().exec("tasklist");
				final InputStream[] ins = { p.getInputStream(),
						p.getErrorStream() };
				for (int i = 0; i < ins.length; i++) {
					try {
						InputStream in = ins[i];
						byte[] b = new byte[1024];
						int len = 0;
						ByteArrayOutputStream bao = new ByteArrayOutputStream();
						while ((len = in.read(b)) > 0) {
							bao.write(b, 0, len);
						}
						in.close();
						String s = new String(bao.toByteArray());
						bao.close();

						processes.add(s);

					} catch (Exception e) {
						logger.log(Level.SEVERE, e.getMessage(), e);
					}
				}
				p.waitFor();
				checkProcess();
			} catch (Exception e) {
				logger.log(Level.SEVERE, e.getMessage(), e);
			}
			try {
				sleep(headlessPidCheckInterval);
			} catch (InterruptedException e) {
				logger.log(Level.SEVERE, e.getMessage(), e);
			}
		}
	}

	private void checkProcess() {
		// System 4 Services 0 2,824 K

		// index 0 is normal input stream text, not error message
		synchronized (headlesspidCheckLock) {
			headlessAlive = false;
			String[] processesInfos = ((String) processes.get(0)).split("\r\n");
			for (int i = 0; i < processesInfos.length; i++) {
				String processInfo = processesInfos[i];
				if (processInfo.trim().equals("")) {
					continue;
				}
				String[] sp = processInfo.split(" ");
				int index = -1;
				for (int n = 0; n < sp.length; n++) {
					// the previous number before "Services" session name
					if (sp[n].equals("Services") || sp[n].equals("Console")
							|| sp[n].indexOf("RDP-Tcp") >= 0) {
						index = n - 1;
						break;
					}
				}
				if (index > 0) {
					String pid = sp[index];

					if (pid.equals(headlesspid)) {
						// System.out.println("process info: "+processInfo);
						headlessAlive = true;
						break;
					}
				}

			}
			// System.out.println(processes.get(0));
			// logger.info("process "+headlesspid+" status: "+headlessAlive);
			if (!headlessAlive) {
				logger.log(Level.INFO,
						"Headless pid not exist in task list, may be killed unexpectedly, process quit");
				System.exit(0);
			}
		}
	}

}
